



class Block {
    
    public _x: number = 0;

    public _y: number = 0;
    
    public _side: number = 0;

    /** 是否为障碍物 */
    public _iswall: boolean = false;
    
    public F: number = 0;

    public G: number = 0;
    
    public H: number = 0;

    public isOpen: boolean = false;

    public isClose: boolean = false;

    public _color: cc.Color = null;
    
    constructor( x, y, side, color ) {
        
        this._x = x;
        this._y = y;
        this._side = side;
        this._color = color;
        
    }
    
}

export enum PointType{
    
    /** 超出界面 */
    esidegird = "esidegird",
    /** 普通点 */
    normalgird = "normal_gird",
    /** 起始点 */
    startgird = "start_gird",
    /** 终点 */
    end_gird = "end_gird",
}


/** 统一坐标， 以左下角为原点  */
export class Gird {
    

    private startpos: cc.Vec2 = cc.v2( 0, 0 );

    private blockSide: number = 0;

    private row: number = 0;
    
    private col: number = 0;

    public startBlock: cc.Vec2 = cc.v2( 1, 3 );

    public endBlock: cc.Vec2 = cc.v2( 3, 5 );

    public blockArray: Array<Block> = new Array();


    constructor( x, y, blockSide, row, col ) {

        this.startpos.x = x;
        this.startpos.y = y;
        this.blockSide = blockSide;
        this.row = row;
        this.col = col;

        this.blockinit();
        this.blockplayerpos();
        
    }

    /**  初始化格子 ,以左下角为原点   */
    private blockinit () {

        for( let i = 0; i < this.col; i++){
            for( let j = 0; j < this.row; j++){
                let color = new cc.Color(190, 190, 190, 255);
                let grid = cc.v2(j, i);
                let position = this.girdToPosition( grid );
                let block = new Block(position.x, position.y, this.blockSide, color)
                this.blockArray.push( block );
            }
        }
    }

    /** 初始化玩家位置 */
    private blockplayerpos () {

        let startindex = this.getblockArrayIndex( this.startBlock );
        let endindex = this.getblockArrayIndex( this.endBlock );
        this.blockArray[ startindex ]._color = new cc.Color(255, 0, 0, 255);
        this.blockArray[ endindex ]._color =  new cc.Color(0, 0, 255, 255);
        
    }

    /** 根据格子坐标获取数字下标 */
    public getblockArrayIndex ( grid: cc.Vec2 ) {
        let index = grid.y * this.row + grid.x;
        return index;
    }

    /** 获取当前坐标周围点 */
    public getPosNearFourPosNum (grid: cc.Vec2){
        
        let nearList: cc.Vec2[] = [];
        let up_pos = cc.v2( grid.x, grid.y + 1);
        let up_index = this.getblockArrayIndex(up_pos);
        if(grid.y + 1 < this.col && !this.blockArray[up_index]._iswall){
            nearList.push(up_pos);
        };
        let down_pos = cc.v2( grid.x, grid.y - 1);
        let down_index = this.getblockArrayIndex(down_pos);
        if(grid.y - 1 >= 0 && !this.blockArray[down_index]._iswall){
            nearList.push(down_pos);
        };
        let left_pos = cc.v2( grid.x -1, grid.y);
        let left_index = this.getblockArrayIndex(left_pos);
        if(grid.x - 1 >= 0 && !this.blockArray[left_index]._iswall){
            nearList.push(left_pos);
        };
        let right_pos = cc.v2( grid.x + 1, grid.y);
        let right_index = this.getblockArrayIndex(right_pos);
        if(grid.x + 1 < this.row && !this.blockArray[right_index]._iswall){
            nearList.push(right_pos);
        };
        let startIndex = this.getblockArrayIndex(this.startBlock);
        let nearIndexs = this.getIndexArray(nearList);
        for(let i = 0; i < nearIndexs.length; i++){
            
            if( nearIndexs[i] == startIndex){
                nearIndexs.splice(i,1);
                i--;
            }
        }
        nearList = this.getPosArray(nearIndexs);
        cc.log(nearList);
        return nearList;
    }

    public getIndexArray ( posList: cc.Vec2[] ){
        
        let arr = [];
        posList.forEach((pos)=>{
            let index = this.getblockArrayIndex(pos);
            arr.push(index);
        });
        return arr;
    }

    private getblockPos ( index: number ){
        let pos = cc.v2(0,0);
        pos.y = Math.floor(index / this.row);
        pos.x  = index % this.row;
        return pos;
    }

    private getPosArray ( nearIndexs:  number[] ){

        let nearList: cc.Vec2[] = [];
        nearIndexs.forEach((index)=>{
            let pos = this.getblockPos(index);
            nearList.push(pos);
        });
        return nearList;
    }

    private girdToPosition ( grid: cc.Vec2 ) {

        let offsetx = 2;
        let offsety = 2;
        let pos = cc.v2(0, 0);
        pos.x = this.startpos.x + (this.blockSide + offsetx) * grid.x;
        pos.y = this.startpos.y + (this.blockSide + offsety) * grid.y;
        return pos;
    }

    /** 交换两点 */
    public changePoint ( type: PointType, pos: cc.Vec2 ) {

        switch (type) {
            case PointType.startgird:{
                let index = this.getblockArrayIndex( pos );
                if( index ){

                    let startindex = this.getblockArrayIndex( this.startBlock );
                    this.blockArray[ startindex ]._color = new cc.Color(190, 190, 190, 255);
                    this.startBlock = pos;
                    this.blockArray[ index ]._color = new cc.Color(255, 0, 0, 255);
                }
                break;   
                
            }   
            case PointType.end_gird:{
                let index = this.getblockArrayIndex( pos );
                if( index ){

                    cc.log(pos);
                    let endindex = this.getblockArrayIndex( this.endBlock );
                    this.blockArray[ endindex ]._color = new cc.Color(190, 190, 190, 255);
                    this.endBlock = pos;
                    this.blockArray[ index ]._color =  new cc.Color(0, 0, 255, 255);
                }
                break;
            }
                
            default:
                break;
        }
    }

    /** 检测点是否在格子内 
     *  通过计算该点到初始点的距离来判断是否在格子内
    */
    public checkPositionINgird ( pos: cc.Vec2 ):{ type: PointType, index: cc.Vec2 } {

        let right = this.startpos.x + (this.blockSide + 2) * this.row;
        if( pos.x < this.startpos.x || pos.x > right){
            return { type: PointType.esidegird, index: cc.v2(0,0) };
        }
        let up = this.startpos.y + (this.blockSide + 2) * this.col;
        if( pos.y < this.startpos.y || pos.y > up){
            return { type: PointType.esidegird, index: cc.v2(0,0) };
        }
        let leng = this.blockSide + 2;
        let x_leng = Math.abs( this.startpos.x - pos.x );
        let y_leng = Math.abs( this.startpos.y - pos.y );

        let posx = Math.floor( x_leng / leng );
        let posy = Math.floor( y_leng / leng );
        
        let rectpos = cc.v2( this.startpos.x + posx * leng, this.startpos.y + posy * leng );
        if( 
            pos.x > rectpos.x && pos.x < rectpos.x + this.blockSide
            && pos.y > rectpos.y && pos.y < rectpos.y + this.blockSide
        )
        {
            let pointType = this.checkPointType( cc.v2( posx, posy ));
            let pos = cc.v2( posx, posy);
            return { type: pointType, index: pos };
        }
        return { type: PointType.esidegird, index: cc.v2(0,0) };
    }

    /** 设置当前格子为墙体, 已经是墙体就取消  */
    public setWall ( pos: cc.Vec2 ){
        let index = pos.x + pos.y * this.row;
        this.blockArray[index]._iswall = true;
        this.blockArray[index]._color = new cc.Color(50, 50, 50, 255);
    }

    private checkPointType ( pos: cc.Vec2 ){

        let pointType: PointType = PointType.normalgird;
        if( pos.x == this.startBlock.x && pos.y == this.startBlock.y){
            pointType = PointType.startgird;
        }
        if( pos.x == this.endBlock.x && pos.y == this.endBlock.y){
            pointType = PointType.end_gird;
        }
        return pointType;
    }

    public setHasFindpos ( pos: cc.Vec2 ){
        let index = this.getblockArrayIndex(pos);
        this.blockArray[index]._color = new cc.Color(100, 100, 100, 255);
    }
}